import { readFileSync } from '../io.js'
import Runtime from '../runtime.js'
import input from './stream/input.js'
import token from './stream/token.js'
import parser from './parser/index.js'
import interpreter from './interpreter/index.js'
import DebugInfo from '../../debug/print.js'

const compile = async ({ filepath, runtime, type, xrehome }) => {
  const _runtime = runtime || new Runtime()
  _runtime.config.set('X_HOME', xrehome)

  const config = _runtime.config

  const code = readFileSync(filepath)

  if (config.get('PRINT_SOURCE_CODE')) {
    const debugInfo = new DebugInfo('Source code', filepath)
    debugInfo.start()
    code.split('\n').forEach(line => debugInfo.print(line))
    debugInfo.end()
  }

  const inputs = input(code)

  if (config.get('PRINT_INPUTS')) {
    const debugInfo = new DebugInfo('Inputs', filepath)
    debugInfo.start()

    const temp_inputs = input(code)
    const inputs = []
    let index = 0

    while (!temp_inputs.eof()) {
      inputs[index] = inputs[index] || []
      const token = temp_inputs.next()
      if (token === '\n') {
        index++
      } else {
        inputs[index].push(token)
      }
    }

    for (const input of inputs) {
      debugInfo.print(input)
    }

    debugInfo.end()
  }

  const tokens = token(inputs)

  if (config.get('PRINT_TOKENS')) {
    const debugInfo = new DebugInfo('Tokens', filepath)
    debugInfo.start()

    const temp_inputs = input(code)
    const temp_tokens = token(temp_inputs)
    while (!temp_tokens.eof()) {
      debugInfo.print(temp_tokens.next())
    }

    debugInfo.end()
  }

  const ast = parser(tokens, filepath, type)

  if (config.get('PRINT_AST')) {
    const debugInfo = new DebugInfo('AST', filepath)
    debugInfo.start()
    debugInfo.print(ast)
    debugInfo.end()
  }

  return await interpreter(_runtime, ast)
}

export default compile